#!/usr/bin/env python

class Alphabet:
    Base26 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    Base36 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    Base62 = '0123456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'


# this function in based on code posted on stackoverflow.com
def encode(number, alphabet, min_length=0):
    baseX = ''
    negative = False
    alphabet_length = len(alphabet)
    min_length = abs(min_length)

    if number < 0:
        negative = True
        number = abs(number)

    if 0 <= number < alphabet_length:
        baseX = alphabet[number]
    else:
        while number != 0:
            number, i = divmod(number, alphabet_length)
            baseX = alphabet[i] + baseX

    baseX_length = len(baseX)
    while baseX_length < min_length:
        baseX = alphabet[0] + baseX
        baseX_length += 1

    return '-'+ baseX if negative else baseX


class Multiencoding:
    def __init__(self, data, decode=None):
        if isinstance(data, (list)):
            index = 0
            data_length = len(data)
            while index < data_length:
                data[index] = self._sanitize_(data[index])
                index += 1
        else:
            raise TypeError('expects a list of tuples')

        if isinstance(decode, (int)):
            index = len(data) - 1
            while index > 0:
                val, bit = data[index]
                remainder = decode>>bit
                data[index] = (decode - (remainder<<bit), bit)
                decode = remainder
                index -= 1

            val, bit = data[0]
            data[0] = (remainder, bit)            

        self.data = data

    def _sanitize_(self, tbl):
        try:
            val, bit = tbl
            if not val > 2**bit:
                return (int(val), int(bit))
        except TypeError:    
            raise TypeError('expects a tuple with two integers')

        raise ValueError('insufficient bits for representing value'+str(tbl))

    def __int__(self):
        value = None
        for val, bit in self.data:
            value = val if value is None else (value<<bit) + val

        return value

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, tbl):
        self.data[index] = self._sanitize_(tbl)

    def __iter__(self):
        return iter(self.data)

    def __len__(self):
        return len(self.data)

    def __eq__(self, other):
        return self.data == other

    def __str__(self):
        return str(self.data) +' : '+ str(self.__int__())



#if __name__ == '__main__':
#    ds1 = [(53,6), (0, 4)]
#    ds2 = [(86000,17), (86370, 17), (511, 10)]
#
#    dp1 = Multiencoding(ds1)
#    print(dp1)
#    dp2 = Multiencoding(ds2)
#    print(dp2)
#    dp3 = Multiencoding(ds2, int(dp1)-1)
#    print(dp3)
#
#    print(dp1 == dp2)
#
#    print()
#    strng = encode(int(dp1), Alphabet.Base36)
#    print(strng)
#    print(int(strng, 36))
